import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.util.Scanner;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

/**
 * WeatherAPI.com 天气服务实现
 * 提供第二个主要天气数据源，支持免费层和高级API
 */
public class WeatherAPIComService implements WeatherAPIService {
    
    private String baseURL = "https://api.weatherapi.com/v1/";
    private UserPreferences userPreferences;
    private boolean serviceAvailable = true;
    private long lastConnectionTest = 0;
    private static final long CONNECTION_TEST_CACHE_MS = 300000; // 5分钟缓存
    
    public WeatherAPIComService(UserPreferences userPreferences) {
        this.userPreferences = userPreferences;
        // WeatherAPI.com 默认使用公制单位
        this.userPreferences.setPreferredUnits("metric");
    }
    
    @Override
    public String getSourceId() {
        return "weatherapi";
    }
    
    @Override
    public String getDisplayName() {
        return "WeatherAPI.com";
    }
    
    @Override
    public boolean isServiceAvailable() {
        // 如果没有有效的API密钥，服务不可用
        if (getApiKey().equals("")) {
            return false;
        }
        
        // 缓存连接测试结果
        long currentTime = System.currentTimeMillis();
        if (currentTime - lastConnectionTest > CONNECTION_TEST_CACHE_MS) {
            serviceAvailable = testConnection() > 0;
            lastConnectionTest = currentTime;
        }
        return serviceAvailable;
    }
    
    @Override
    public String getBaseURL() {
        return baseURL;
    }
    
    @Override
    public String getAPILimits() {
        return "1000 calls/month (Free tier), Real-time weather data";
    }
    
    @Override
    public boolean isLocationSupported(Location location) {
        return location != null && 
               location.getCity() != null && 
               !location.getCity().trim().isEmpty();
    }
    
    @Override
    public int getPriority() {
        return 2; // 中等优先级
    }
    
    @Override
    public long testConnection() {
        if (getApiKey().equals("")) {
            System.out.println("WeatherAPI.com: No API key configured");
            return -1;
        }
        
        try {
            long startTime = System.currentTimeMillis();
            String testEndpoint = baseURL + "current.json?key=" + getApiKey() + "&q=London";
            
            URL url = URI.create(testEndpoint).toURL();
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("HEAD");
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);
            conn.setRequestProperty("User-Agent", "WeatherApp/1.0");
            
            int responseCode = conn.getResponseCode();
            conn.disconnect();
            
            if (responseCode == 200) {
                long latency = System.currentTimeMillis() - startTime;
                System.out.println("WeatherAPI.com connection test successful, latency: " + latency + "ms");
                return latency;
            } else {
                System.err.println("WeatherAPI.com connection test failed with code: " + responseCode);
                return -1;
            }
            
        } catch (Exception e) {
            System.err.println("WeatherAPI.com connection test error: " + e.getMessage());
            return -1;
        }
    }
    
    @Override
    public APISourceInfo.APIStatus getAPIStatus() {
        if (!isServiceAvailable()) {
            return APISourceInfo.APIStatus.ERROR;
        }
        
        long latency = testConnection();
        if (latency < 0) {
            return APISourceInfo.APIStatus.ERROR;
        } else if (latency > 3000) {
            return APISourceInfo.APIStatus.ERROR;
        } else {
            return APISourceInfo.APIStatus.ONLINE;
        }
    }
    
    @Override
    public WeatherData getCurrentWeather(Location location) throws RuntimeException {
        if (!isServiceAvailable()) {
            throw new RuntimeException("WeatherAPI.com service is not available");
        }
        
        if (!isLocationSupported(location)) {
            throw new RuntimeException("Location not supported: " + 
                (location != null ? location.getCity() : "null"));
        }
        
        String response = fetchWeatherData(location, "current");
        return parseCurrentWeatherResponse(response);
    }
    
    @Override
    public WeatherData[] getForecast(Location location, int days) throws RuntimeException {
        if (!isServiceAvailable()) {
            throw new RuntimeException("WeatherAPI.com service is not available");
        }
        
        if (!isLocationSupported(location)) {
            throw new RuntimeException("Location not supported: " + 
                (location != null ? location.getCity() : "null"));
        }
        
        // WeatherAPI.com 支持天数检测和限制
        int requestDays = getMaxSupportedDays(days);
        String response = fetchWeatherData(location, "forecast", requestDays);
        return parseForecastResponse(response, requestDays);
    }
    
    /**
     * 获取API支持的最大天数
     * @param requestedDays 请求的天数
     * @return 实际支持的天数
     */
    private int getMaxSupportedDays(int requestedDays) {
        // 检测API计划类型
        if (isPaidPlan()) {
            // 付费计划支持最多14天预报
            return Math.min(requestedDays, 14);
        } else {
            // 免费层最多支持3天预报
            return Math.min(requestedDays, 3);
        }
    }
    
    /**
     * 检测是否为付费API计划
     * 注意：这是一个简化的检测逻辑，实际情况可能需要通过API调用来验证
     * @return true如果是付费计划，false如果是免费计划
     */
    private boolean isPaidPlan() {
        // 简化的检测逻辑：
        // 1. 检查API key的特征（付费key通常有特定格式）
        // 2. 或者通过配置文件指定
        // 3. 或者通过实际API调用测试
        
        String apiKey = getApiKey();
        // 如果API key为空或长度不足，肯定是免费层
        if (apiKey.length() < 32) {
            return false;
        }
        
        // 默认假设为免费层，除非有明确的付费计划配置
        // 用户可以在配置中明确指定付费计划状态
        return false; // 暂时默认为免费层，避免超出限制
    }
    
    private String fetchWeatherData(Location location, String endpointType) {
        return fetchWeatherData(location, endpointType, 0);
    }
    
    private String fetchWeatherData(Location location, String endpointType, int days) {
        StringBuilder endpoint = new StringBuilder();
        endpoint.append(baseURL).append(endpointType).append(".json");
        endpoint.append("?key=").append(getApiKey());
        endpoint.append("&q=").append(location.getCity().replace(" ", "%20"));
        
        if ("forecast".equals(endpointType) && days > 0) {
            endpoint.append("&days=").append(days);
        }
        
        // 添加AQI（空气质量指数）信息，如果API支持
        endpoint.append("&aqi=no"); // 免费层通常不包括AQI
        
        System.out.println("WeatherAPI.com Request URL: " + endpoint.toString());
        
        StringBuilder response = new StringBuilder();
        
        try {
            URL url = URI.create(endpoint.toString()).toURL();
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(8000);
            conn.setReadTimeout(8000);
            conn.setRequestProperty("User-Agent", "WeatherApp/1.0");
            
            int responseCode = conn.getResponseCode();
            
            if (responseCode == 200) {
                Scanner sc = new Scanner(conn.getInputStream());
                while (sc.hasNext()) {
                    response.append(sc.nextLine());
                }
                sc.close();
            } else {
                String errorMessage = getErrorMessage(responseCode, location.getCity());
                serviceAvailable = false;
                throw new RuntimeException(errorMessage);
            }
            
            conn.disconnect();
            
        } catch (java.io.FileNotFoundException e) {
            serviceAvailable = false;
            throw new RuntimeException("City '" + location.getCity() + "' not found in WeatherAPI.com");
        } catch (java.net.SocketTimeoutException e) {
            serviceAvailable = false;
            throw new RuntimeException("WeatherAPI.com request timeout");
        } catch (java.net.UnknownHostException e) {
            serviceAvailable = false;
            throw new RuntimeException("Unable to connect to WeatherAPI.com");
        } catch (java.io.IOException e) {
            serviceAvailable = false;
            throw new RuntimeException("WeatherAPI.com network error: " + e.getMessage());
        } catch (Exception e) {
            if (e instanceof RuntimeException) {
                throw e;
            }
            serviceAvailable = false;
            throw new RuntimeException("WeatherAPI.com error: " + e.getMessage());
        }
        
        System.out.println("WeatherAPI.com Response: " + response.toString());
        return response.toString();
    }
    
    private WeatherData parseCurrentWeatherResponse(String response) {
        try {
            if (response == null || response.trim().isEmpty()) {
                throw new RuntimeException("Empty response from WeatherAPI.com");
            }
            
            JsonObject jsonObj = JsonParser.parseString(response).getAsJsonObject();
            
            // 检查错误
            if (jsonObj.has("error")) {
                JsonObject error = jsonObj.getAsJsonObject("error");
                String message = error.has("message") ? 
                    error.get("message").getAsString() : "Unknown error";
                throw new RuntimeException("WeatherAPI.com error: " + message);
            }
            
            JsonObject current = jsonObj.getAsJsonObject("current");
            
            // WeatherAPI.com 使用不同的字段名
            double temp = current.get("temp_c").getAsDouble(); // 直接获取摄氏度
            double humidity = current.get("humidity").getAsDouble();
            double windSpeed = current.get("wind_kph").getAsDouble() / 3.6; // 转换为 m/s
            String description = current.getAsJsonObject("condition").get("text").getAsString();
            
            System.out.println("WeatherAPI.com parsed temperature: " + temp + "°C");
            
            return new WeatherData(temp, humidity, windSpeed, description, "Current", userPreferences);
            
        } catch (Exception e) {
            if (e instanceof RuntimeException) {
                throw e;
            }
            throw new RuntimeException("Failed to parse WeatherAPI.com current weather data: " + e.getMessage());
        }
    }
    
    private WeatherData[] parseForecastResponse(String response, int days) {
        try {
            JsonObject jsonObj = JsonParser.parseString(response).getAsJsonObject();
            
            // 检查错误
            if (jsonObj.has("error")) {
                JsonObject error = jsonObj.getAsJsonObject("error");
                String message = error.has("message") ? 
                    error.get("message").getAsString() : "Unknown error";
                throw new RuntimeException("WeatherAPI.com forecast error: " + message);
            }
            
            JsonObject forecast = jsonObj.getAsJsonObject("forecast");
            JsonArray forecastDays = forecast.getAsJsonArray("forecastday");
            
            int actualDays = Math.min(days, forecastDays.size());
            WeatherData[] forecastData = new WeatherData[actualDays];
            
            for (int i = 0; i < actualDays; i++) {
                JsonObject dayData = forecastDays.get(i).getAsJsonObject();
                JsonObject day = dayData.getAsJsonObject("day");
                
                // 使用平均温度
                double temp = day.get("avgtemp_c").getAsDouble();
                double humidity = day.get("avghumidity").getAsDouble();
                double windSpeed = day.get("maxwind_kph").getAsDouble() / 3.6; // 转换为 m/s
                String description = day.getAsJsonObject("condition").get("text").getAsString();
                
                // 获取日期
                String date = dayData.get("date").getAsString();
                String dateTime = "Forecast " + date;
                
                forecastData[i] = new WeatherData(temp, humidity, windSpeed, description, dateTime, userPreferences);
            }
            
            return forecastData;
            
        } catch (Exception e) {
            if (e instanceof RuntimeException) {
                throw e;
            }
            throw new RuntimeException("Failed to parse WeatherAPI.com forecast data: " + e.getMessage());
        }
    }
    
    private String getErrorMessage(int responseCode, String cityName) {
        switch (responseCode) {
            case 400:
                return "Bad request to WeatherAPI.com. Please check the city name: " + cityName;
            case 401:
                return "WeatherAPI.com authentication failed. Invalid API key.";
            case 403:
                return "WeatherAPI.com access forbidden. API key may be disabled or exceed quota.";
            case 404:
                return "City '" + cityName + "' not found in WeatherAPI.com database.";
            case 429:
                return "WeatherAPI.com rate limit exceeded. Please wait before making more requests.";
            case 500:
                return "WeatherAPI.com server error. Please try again later.";
            case 503:
                return "WeatherAPI.com service unavailable. Please try again later.";
            default:
                return "WeatherAPI.com error. HTTP code: " + responseCode;
        }
    }
    
    /**
     * 获取 WeatherAPI.com 的 API 密钥
     */
    private String getApiKey() {
        String key = userPreferences.getWeatherApiComKey();
        return (key != null) ? key.trim() : "";
    }
} 